import React, {FC, useCallback, useEffect, useMemo, useRef, useState} from "react";
import "./css/SelectUploadImage.less";
import {Button, Spin, Upload} from "antd";
import GlobalIcon from "../../global/GlobalIcon.tsx";

import {getThumbById, uploadFile} from "../../services/FileService.tsx";
import {isString} from "../../utils";
import useStateRef from "../../customUse/useStateRef.tsx";
import {previewFile} from "@core/services/PreviewService";

interface SelectUploadImageProps {
    value?: any,
    ds?: any,
    mode?: "single" | "multiple",
    uploadNum?: number,
    disabled: boolean,
    onChange: Function,
    joinKey?: string,
    isCreateThumb: boolean
}

const SelectUploadImage: FC<SelectUploadImageProps> = (props) => {
    const loadingCountRef = useRef(0);

    const fileListRef: any = useRef([])

    const [fileList, setFileList] = useStateRef([], fileListRef),
        [loading, setLoading] = useStateRef(0, loadingCountRef);

    const handleChange: Function = useCallback((ids: string[]) => {
        const {joinKey, mode = "single"}: {
            joinKey?: string,
            mode?: "single" | "multiple"
        } = props;
        let value: any;
        if (mode === "multiple") {
            value = joinKey ? ids.join(joinKey) : ids;
        } else {
            value = ids[0];
        }
        props.onChange && props.onChange(value);
    }, [props.onChange, props.joinKey, props.mode])

    const setFileValue: Function = useCallback((files: any[]) => {
        let newFileList: any[] = [...fileListRef.current, ...files];
        let {uploadNum = 1} = props
        if(newFileList.length > uploadNum) {
            return
        }
        let ids: string[] = [];
        newFileList = newFileList.map((item: any) => {
            let url: string = item.url || (window.location.origin + getThumbById(item.id))
            ids.push(item.id)
            return {
                ...item,
                url
            }
        });
        handleChange(ids);
        setFileList(newFileList);
    }, [fileList, props.onChange, props.joinKey, props.mode]);

    const handleUploadFile: Function = useCallback(async (file: any) => {
        setLoading((loadingCountRef.current + 1));
        const res = await uploadFile(file, props.isCreateThumb);
        setLoading((loadingCountRef.current - 1));
        setFileValue([res])
    }, [fileList, props.onChange, props.joinKey, props.mode, props.isCreateThumb]);

    const handlePreviewFile: Function = useCallback((file: any) => {
        previewFile(file, {
            fileIdField: "id",
            isShowVersion: false
        })
    }, []);

    const handleRemove: Function = useCallback((file: any) => {
        let newFileList: any[] = [...fileList];
        let index: number = fileList.findIndex(i => (i.id === file.id));
        if (index === -1) {
            return false
        }
        newFileList.splice(index, 1);
        let ids: string[] = newFileList.map(i => (i.id));
        handleChange(ids);
        setFileList(newFileList);
    }, [fileList, props.onChange, props.joinKey, props.mode]);


    useEffect(() => {
        const {ds = {}, mode = "single", joinKey = ","}: {
            ds?: any,
            mode?: "single" | "multiple",
            joinKey?: string
        } = props;
        let newValue = ds.value || props.value;
        if (newValue && isString(newValue)) {
            newValue = newValue.split(joinKey);
        }
        if (newValue && newValue.length) {
            if (mode === "multiple") {
                setFileList(newValue.map((key: string) => {
                    let url: string = window.location.origin + getThumbById(key);
                    return {
                        id: key,
                        url
                    }
                }))
            } else {
                setFileList([newValue[0]].map((key: string) => {
                    let url: string = window.location.origin + getThumbById(key);
                    return {
                        id: key,
                        url
                    }
                }));
            }
        }
    }, [props.ds, props.uploadNum, props.joinKey, props.mode]);


    const renderBtn = useMemo(() => {
        return (
            <div className="sf_core_upload_image_btn">
                <Button icon={<GlobalIcon name="icon-create"/>}/>
            </div>
        )
    }, []);

    const renderSelectUploadImage = useMemo(() => {
        let {uploadNum = 1, mode = "single"}: { uploadNum?: number, mode?: "single" | "multiple" } = props;
        if (mode !== "multiple") {
            uploadNum = 1;
        }
        return (
            <Spin spinning={loading} wrapperClassName="sf_core_upload_image">
                <Upload
                    multiple={mode === "multiple"}
                    listType="picture-card"
                    fileList={fileList}
                    disabled={props.disabled}
                    onPreview={(file) => {
                        handlePreviewFile(file);
                        return false;
                    }}
                    beforeUpload={(file) => {
                        handleUploadFile(file);
                        return false
                    }}
                    onRemove={(file) => {
                        handleRemove(file);
                        return false
                    }}
                >
                    {fileList.length < uploadNum && !props.disabled ? renderBtn : null}
                </Upload>
            </Spin>
        )
    }, [loading, fileList, props.onChange, props.uploadNum, props.joinKey, props.disabled, props.mode, props.isCreateThumb]);
    return (renderSelectUploadImage);
};

export default React.memo(SelectUploadImage);